/**
 * 组件旋转功能
 */
import mouseObserver from '@/utils/MouseMoveObserver';

export default class Rotate {

    mouseObserver = null;

    // d3实例
    d3Instance = null;

    // 容器
    container = null;

    // 选中元素
    selection = null;

    // 是否正在旋转
    isRotating = false;

    // 鼠标按下时的角度
    mouseDownAngle = 0;

    // 鼠标按下时的元素角度
    elementAngleAtMouseDown = 0;

    // 鼠标按下时的初始角度（用于计算相对变化）
    initialMouseAngle = 0;
   
    // 记录旋转方向  clockwise: 顺时针，counterclockwise: 逆时针
    rotationDirection = null;  

     // 当前角度
    currentAngle = 0      


    // 旋转配置
    config = {
        hotspotDistance: 30,  // 角落热点距离
        rotateInsideDistance: 10, // 在旋转位置的距离（像素）内可旋转
        rotateOutsideDistance: 30, // 在旋转位置的距离（像素）外可旋转
        defaultCursor: 'default', // 默认光标
        rotateCursor: 'grab', // 旋转光标
        rotateSnapThreshold: 10, // 旋转对齐阈值（度）
        rotateSnapStep: 90, // 旋转对齐步长（度）
    };

    constructor(d3Instance, container, mouseObserver, config = {}) {
        this.d3Instance = d3Instance;
        this.container = container;
        this.mouseObserver = mouseObserver;
        this.config = Object.assign(this.config, config);
    }


    // 绑定角落热点事件
    bindPointsEvents = async (selection) => {
        this.selection = selection;
        const that = this;
            
        this.container.selectAll('.rotate-handle')
            .on('mousedown', function(event, d) {
                that.pointMouseDown(event, this, d);
            });
        

        this.mouseObserver.subscribe( function(event, d) {
            that.onDeMouseMove(event, this, d);
        });

        // this.container.on('mousemove', function(event, d) {
        //     that.onDeMouseMove(event, this, d);
        // });

        this.d3Instance.select(window).on("mouseup", function() {
            that.onMouseUp();
        });
    }

    //  鼠标弹起
    onMouseUp = () => {
        if (this.isRotating) {
            this.isRotating = false;
        }
    }

    // 角落热点鼠标按下
    pointMouseDown = (event, that, d) => {
        event.preventDefault();
        this.isRotating = true;
        const data = this.selection.data()[0];
        
        // 获取当前元素的旋转角度（从transform属性或数据中）
        const parent = this.getParentByClassName();
        const currentTransform = parent.attr('transform');
        let currentRotation = 0;
        
        if (currentTransform && currentTransform.includes('rotate')) {
            // 从transform属性中提取旋转角度
            const rotateMatch = currentTransform.match(/rotate\(([^,]+)/);
            if (rotateMatch) {
                currentRotation = parseFloat(rotateMatch[1]) || 0;
            }
        } else {
            // 从数据中获取旋转角度
            currentRotation = 0;
        }
        
        this.startAngle = currentRotation;
        this.currentAngle = currentRotation;
        this.elementAngleAtMouseDown = currentRotation;
        
        // 记录鼠标按下时的角度（相对于元素中心）
        const center = this.getSelectionCenter(this.selection);
        const mousePos = this.d3Instance.pointer(event, this.container.node());
        this.mouseDownAngle = this.calculateAngle(center.x, center.y, mousePos[0], mousePos[1]);
        this.initialMouseAngle = this.mouseDownAngle;
        
        this.rotationDirection = null; // 重置旋转方向
    }

    onDeMouseMove = (event, that, d) => {
        if (!this.isRotating) return;

        // 获取组件中心和当前鼠标位置
        const center = this.getSelectionCenter(this.selection);
        const currentPos = this.d3Instance.pointer(event, this.container.node());
        
        // 计算当前鼠标相对于元素中心的角度
        const currentMouseAngle = this.calculateAngle(center.x, center.y, currentPos[0], currentPos[1]);
        
        // 计算鼠标角度相对于按下时的变化
        let mouseAngleChange = currentMouseAngle - this.initialMouseAngle;
        
        // 处理角度跨越360度边界的情况
        if (mouseAngleChange > 180) {
            mouseAngleChange -= 360;
        } else if (mouseAngleChange < -180) {
            mouseAngleChange += 360;
        }
        
        // 新角度 = 鼠标按下时的元素角度 + 鼠标角度变化
        let newAngle = this.elementAngleAtMouseDown + mouseAngleChange;

        // 标准化角度到0-360度
        newAngle = ((newAngle % 360) + 360) % 360;

        // 确定旋转方向
        if (this.rotationDirection === null) {
            this.rotationDirection = mouseAngleChange > 0 ? 'clockwise' : 'counterclockwise';
        }

        // 自动对齐逻辑：仅在接近但未超过目标角度时吸附
        if (this.config.rotateSnapThreshold > 0) {
            // 计算距离最近的snapThreshold的倍数
            const rotateSnapStep = this.config.rotateSnapStep;
            const modulo = newAngle % rotateSnapStep;
            const nearestAngle = modulo < rotateSnapStep / 2 ? 
                                Math.floor(newAngle / rotateSnapStep) * rotateSnapStep :
                                Math.ceil(newAngle / rotateSnapStep) * rotateSnapStep;

            // 检查是否在阈值范围内且未超过目标
            const diff = Math.abs(newAngle - nearestAngle);

            // 根据旋转方向判断是否应该吸附
            if (diff < this.config.rotateSnapThreshold) {
                // 顺时针旋转是，只吸附到当前接近且未超过的rotateSnapStep倍数
                if (this.rotationDirection === "clockwise" && newAngle <= nearestAngle) {
                    newAngle = nearestAngle;
                }

                // 逆时针旋转时，只吸附到当前接近且未超过的90度倍数
                else if (this.rotationDirection === "counterclockwise" && newAngle >= nearestAngle) {
                    newAngle = nearestAngle;
                }
            }
        }

        // 更新角度并应用旋转
        this.currentAngle = newAngle;

        const parent =  this.getParentByClassName();
        const width = parseFloat(this.selection.attr('width'));
        const height = parseFloat(this.selection.attr('height'));
        const  x  = Number(this.selection.attr('x'));   
        const  y  = Number(this.selection.attr('y'));   


        // 基于元素中心进行旋转：先移动到中心，然后旋转，再移动回原位置
        parent.attr("transform", `rotate(${newAngle}, ${x +  width / 2}, ${y + height  / 2})`);
    }

    // 计算selection在container上的中心店
    getSelectionCenter = (selection) => {
        const x = Number(selection.attr('x'));
        const y = Number(selection.attr('y'));
        const width = Number(selection.attr('width'));
        const height = Number(selection.attr('height'));
        const centerX = x + width / 2;
        const centerY = y + height / 2;

        return {x: centerX, y: centerY};
    }

    // 计算两点之间的角度
    calculateAngle = (cx, cy, x, y) => {
        // 使用反正切函数计算角度（弧度），转换为度
        return Math.atan2(y - cy, x - cx) * 180 / Math.PI;
    }

    // 通过 className获取 父级元素
    getParentByClassName = () => {
        const parentNode = this.selection.node().parentNode;
        const className = parentNode.classList[0];
        const parent = this.container.select(`.${className}`);
        return parent;
    }
}